#include <mips/regdef.h>
#include <sys/syscall.h>
		##INI - Vector "const char *odump_errmsg[]" que contiene los mensajes de error
        .rdata
        .align  2
		mens0:
	        .asciiz  "lectura/escritura OK\n"
		mens1:
	        .asciiz  "lectura/escritura erronea\n"
		mens2:
	        .asciiz  "Delimitador incorrecto\n"
	    mens3:
	        .asciiz  "Caracter invalido\n"

	    .globl  odump_errmsg
	    odump_errmsg:
        .word   mens0
        .word   mens1
        .word   mens2
        .word   mens3

       .data
		lectura:
			.space	1
		escritura:
			.space	1
		octalByte:
			.space	4

		##FIN - Vector "const char *odump_errmsg[]" que contiene los mensajes de error

		##		STACK FRAME DECODE
		##	tengo 3 parametros punteros,
		##	6 variables locales y
		##	es no leaf con 2 parametros (llama a convertir)
		##
		##	  68|--------------|
		##		|     opt	   |
		##	  64|--------------|
		##		|	   fout    |
		##	  60|--------------|
		##		|      f       |
		##	  56|--------------|
		##		|\\\\\\\\\\\\\\|
		##	  52|--------------|
		##		|      ra      |
		##	  48|--------------|	R
		##		|	   fp      |	A
		##	  44|--------------|
		##		|      gp      |
		##	  40|--------------|#---
		##	  	|    int k     |
		##	  36|--------------|
		##	  	|     int j    |	L
		##	  32|--------------|	T
		##	  	|     int mid  |	A
		##	  28|--------------|
		##	  	|     int conv |
		##	  24|--------------|
		##	  	| 	  int i    |
		##	  20|--------------|
		##	  	|     int bin  |
		##	  16|--------------|#---
		##		|\\\\\\\\\\\\\\|
		##	  12|--------------|	A
		##		| int delim	   |    B
		##	   8|--------------|	A
		##		|    int i     |
		##	   4|--------------|
		##		||char bin|\\\\|
		##	   0|--------------|#--

	.text                   	# codigo en sector del texto
	.align 2
	.ent 	odump_decode        # declaro el nombre de la funcion
	.globl 	odump_decode       	# declaro que sera global

odump_decode:
	.frame 	$fp,56,ra			# defino mi frame
	.set 	noreorder
	.cpload t9
	.set 	reorder

	subu 	sp,sp,56			# sp apunta al final

	.cprestore 40				# salvo a gp
	sw 		$fp,44(sp)			# salvo a fp
	sw 		ra,48(sp)			# como es caller, salvo a ra

	move 	$fp,sp				# fp apunta donde apunta sp

	## Guardo los argumentos que le pasan a la funcion

	sw		a0,56($fp)			# recibo el file descriptor del input
	sw		a1,60($fp)			# recibo el file descriptor del output
	sw		a2,64($fp)			# recibo el puntero al opt

	move	s0,a0
	move	s1,a1
	move	s2,a2

	lw		s3,4(s2)			# busco el delim del opt

	## defino e inicializo variables locales

	sw 		zero,24($fp)		# conv=0
	sw 		zero,28($fp)		# mid=0

	## comienza codigo

	move 	a0,s3					# leo delim del struct
	jal 	mystrlen

	move 	t0, v0
	sw 		t0, 32($fp)			#j=strlen(delim)

	sb		zero,lectura
	move	a0, s0				# a0=file descriptor
	la		a1, lectura			# a1=bin
	li		a2, 1				# a2=1
	jal		my_read				# bin=fgetc(f)

	beqz	v0,errorLectura

	lb		t0,lectura
	sw		t0,16($fp)

while:
	lw		t0,16($fp)
	beqz 	t0, fin_while   	#si feof(f) es 0 termina el while

	li 		t5, 2
	sw		t5, 20($fp)			#i=2

for:
	lw 		t5, 20($fp)
	bltz 	t5, fin_for			#si i<0 me voy del for

	lbu   	a0, 16($fp)			#a0=bin
	lw   	a1, 20($fp)			#a1=i
	jal 	convertir			# preparo parametros y llamo a convertir

	sw 		v0,24($fp)			#conv=convertir(bin, i)
	lw		t0, 24($fp)

	li 		t1, -1
	beq 	t0, t1, fin_error	# if conv==-1 error

	lw 		t1, 28($fp)			#mid
	add 	t1, t1, t0
	sw 		t1, 28($fp)			#mid=mid+conv

	sb		zero,lectura
	move	a0, s0				# a0=file descriptor
	la		a1, lectura			# a1=bin
	li		a2, 1				# a2=1
	jal		my_read				# bin=fgetc(f)

	beqz	v0,errorLectura

	lb		t0,lectura
	sw		t0,16($fp)

	lw 		t5, 20($fp)
	sub 	t5, t5, 1
	sw 		t5, 20($fp)			#i--

	j 		for

fin_for:

	sb		zero,escritura

	la		t0,28($fp)
	lw		t0,0(t0)
	sb		t0,escritura

	move	a0, s1				# a0=file descriptor
	la		a1,escritura			# a1=datos
	li		a2, 1				# a2=tamanio

	jal		my_write

	sw 		zero, 28($fp)			#mid=0

	li		t1, 10					#Cargo ASCII '\n'
	lw  	t6, 16($fp)				#if bin=='\n'
	bne 	t6, t1, salto_delimitador

	sb		zero,lectura
	move	a0, s0				# a0=file descriptor
	la		a1, lectura			# a1=bin
	li		a2, 1				# a2=1
	jal		my_read				# bin=fgetc(f)

	beqz	v0,errorLectura

	lb		t0,lectura
	sw		t0,16($fp)

	j 		while

salto_delimitador:

		lw 		t0, 32($fp)			#j
		sw 		t0, 36($fp)			#k=j

loop_delimitador:

		lw 		t1, 36($fp)
		li 		t3,1
		blt 	t1, t3, while		#if k<1

		sb		zero,lectura
		move	a0, s0				# a0=file descriptor
		la		a1, lectura			# a1=bin
		li		a2, 1				# a2=1
		jal		my_read				# bin=fgetc(f)

		beqz	v0,errorLectura

		lb		t0,lectura
		sw		t0,16($fp)

		lw 		t1, 36($fp)
		sub 	t1, t1, 1
		sw 		t1, 36($fp)			#k--

		j 		loop_delimitador

fin_error:
		li 		v0, -1				#devuelvo -1
		j 		fin_while
errorLectura:
		li			v0,1				#devuelvo 1

fin_while:
		move	sp, $fp
		lw		gp, 40(sp)			# restauro gp
		lw		$fp, 44(sp)			# restauro fp
		lw		ra, 48(sp)			# restauro ra
		addu	sp, sp, 56			# restauro sp

		j		ra					# retorno hacia la caller

   		.end odump_decode         	# fin odump_decode
/************************************************************************************************/
	.globl odump_encode
	.ent odump_encode

odump_encode:
	.end odump_encode
/************************************************************************************************/

	.globl my_read
	.ent my_read

my_read:
	   	.frame $fp,32, ra
	   	.set  noreorder
	   	.cpload  t9
	   	.set  reorder

		subu	sp,sp,32

		sw		gp,16(sp)
		sw		$fp,20(sp)
		sw		ra,24(sp)

		move	$fp,sp

		sw		a0,32($fp)
		sw		a1,36($fp)
		sw		a2,40($fp)



		li		v0,SYS_read

		lw		a0,32($fp)
		lw		a1,36($fp)
		lw		a2,40($fp)

		syscall

		bne		a3,zero,read_error


		j		read_unwind

read_error:

	move v0,zero
	addi v1,zero,1

read_unwind:
		lw		gp,16(sp)
		lw		$fp,20(sp)
		lw		ra,24(sp)
		addu		sp,sp,32

		jr		ra

	.end		my_read

	/* ssize_t my_write(int,const void*,size_t) */
	.text
	.align 	2
	.globl	my_write
	.ent		my_write

my_write:
   	.frame $fp,32, ra
   	.set  noreorder
   	.cpload  t9
   	.set  reorder

		subu		sp,sp,32

		sw		gp,16(sp)
		sw		$fp,20(sp)
		sw		ra,24(sp)

		move		$fp,sp

		sw		a0,32($fp)
		sw		a1,36($fp)
		sw		a2,40($fp)

		li		v0,SYS_write

		lw		a0,32($fp)
		lw		a1,36($fp)
		lw		a2,40($fp)

		syscall

		bne		a3,zero,write_error

		beq a3,zero,write_unwind

write_error:
		move v0,zero
		addi v1,zero,1

write_unwind:
		lw		gp,16(sp)
		lw		$fp,20(sp)
		lw		ra,24(sp)
		addu		sp,sp,32

		jr		ra

	.end		my_write

	.ent	mystrlen
mystrlen:
		.frame	$fp, 16, ra
		subu	sp, sp, 16
		.cprestore 0
		sw		$fp, 4(sp)
		move	$fp, sp

		li		v0, 0 				# Use v0 for the result.
		beqz 	a0, mystrlen_return
mystrlen_loop:
		lb		t0, 0(a0)
		beqz	t0, mystrlen_return
		addiu	a0, a0, 1
		addiu	v0, v0, 1
		j		mystrlen_loop

mystrlen_return:

		lw		$fp, 4(sp) 			# Destruimos el frame.
		addu	sp, sp, 16


		j		ra					# Retorno.
		.end	mystrlen


		.ent	convertir
convertir:
		.frame	$fp, 16, ra
		subu 	sp, sp, 16
		sw 		gp, 8(sp)
		sw		$fp, 12(sp)
		move	$fp, sp

		sw 		a0, 16($fp) # busco c
		sw 		a1, 20($fp) # busco i

		sw 		t0, 0($fp) #declaro mult

		beq 	a1,2,igual_64
		beq 	a1,1,igual_8

		li 		t0, 1
		sw 		t0, 0($fp)

comparacion:
		blt 	a0,48,return_menos1
		bge 	a0, 56, return_menos1

		subu 	a0,a0,48
		mult 	t0, a0
		sw 		t0, 0($fp)
		lw 		v0, 0($fp)
		j 		fin_convert
igual_64:
		li 		t0, 64
		sw		t0, 0($fp)
		j 		comparacion
igual_8:
		li 		t0, 8
		sw		t0, 0($fp)
		j 		comparacion

return_menos1:
		li 		v0,-1
		j 		fin_convert

fin_convert:
		lw		gp, 8(sp)
		lw		$fp, 12(sp)
		addu	sp, sp, 16

		j	ra 				# Retorno.

		.end	convertir
